import json
import uuid
import logging
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.utils.decorators import method_decorator
from django.views import View
from django.shortcuts import get_object_or_404
from django.db import transaction
from utils.auth_decorators import login_required, rate_limit
from .models import MedicalImageRecognition, MedicalDocumentOCR, MultiModalConsultation
from .services import MedicalImageRecognitionService, MedicalOCRService, MultiModalAnalysisService

logger = logging.getLogger(__name__)

class ImageRecognitionView(View):
    """图片识别API视图"""
    
    @method_decorator(csrf_exempt)
    @method_decorator(login_required)
    @method_decorator(rate_limit(max_requests=10, window=60))
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
    
    def post(self, request):
        """上传图片进行识别"""
        try:
            if 'image' not in request.FILES:
                return JsonResponse({
                    'code': 400,
                    'msg': '请上传图片文件',
                    'data': None
                }, status=400)
            
            image_file = request.FILES['image']
            recognition_type = request.POST.get('recognition_type', 'symptom')
            user_id = request.user_id
            
            # 验证文件类型和大小
            allowed_types = ['image/jpeg', 'image/jpg', 'image/png']
            if image_file.content_type not in allowed_types:
                return JsonResponse({
                    'code': 400,
                    'msg': '不支持的图片格式，请上传JPG或PNG格式',
                    'data': None
                }, status=400)
            
            if image_file.size > 5 * 1024 * 1024:
                return JsonResponse({
                    'code': 400,
                    'msg': '图片文件过大，请上传小于5MB的图片',
                    'data': None
                }, status=400)
            
            # 创建识别记录
            with transaction.atomic():
                recognition_record = MedicalImageRecognition.objects.create(
                    user_id=user_id,
                    image=image_file,
                    recognition_type=recognition_type,
                    status='processing'
                )
                
                # 调用百度AI识别服务
                service = MedicalImageRecognitionService()
                
                if recognition_type == 'skin':
                    result = service.recognize_skin_condition(image_file)
                elif recognition_type == 'oral':
                    result = service.recognize_oral_condition(image_file)
                elif recognition_type == 'eye':
                    result = service.recognize_eye_condition(image_file)
                else:
                    result = service.recognize_skin_condition(image_file)
                
                # 更新识别结果
                if result.get('success'):
                    recognition_record.status = 'completed'
                    recognition_record.raw_response = result.get('raw_result')
                    recognition_record.recognized_items = result.get('medical_symptoms') or result.get('oral_symptoms') or result.get('eye_symptoms')
                    recognition_record.suggested_diseases = result.get('suggested_diseases', [])
                    recognition_record.suggested_department = result.get('suggested_department')
                    recognition_record.medical_advice = self._generate_medical_advice(result)
                else:
                    recognition_record.status = 'failed'
                
                recognition_record.save()
                
                return JsonResponse({
                    'code': 0,
                    'msg': '识别完成',
                    'data': {
                        'recognition_id': recognition_record.id,
                        'status': recognition_record.status,
                        'result': self._format_recognition_result(recognition_record),
                        'suggested_department': recognition_record.suggested_department,
                        'medical_advice': recognition_record.medical_advice
                    }
                })
                
        except Exception as e:
            logger.error(f"图片识别失败: {e}")
            return JsonResponse({
                'code': 500,
                'msg': f'识别失败: {str(e)}',
                'data': None
            }, status=500)
    
    def _generate_medical_advice(self, result):
        """生成医疗建议"""
        if not result.get('suggested_diseases'):
            return "建议到相关科室进行详细检查"
        
        diseases = result['suggested_diseases'][:3]
        department = result.get('suggested_department', '相关科室')
        advice = f"根据AI识别结果，疑似症状可能涉及：{', '.join(diseases)}。建议尽快到{department}进行专业检查。"
        return advice
    
    def _format_recognition_result(self, recognition):
        """格式化识别结果"""
        if recognition.status != 'completed':
            return None
        
        return {
            'recognized_items': recognition.recognized_items,
            'suggested_diseases': recognition.suggested_diseases
        }
    
    def get(self, request):
        """获取用户的识别历史"""
        try:
            user_id = request.user_id
            page = int(request.GET.get('page', 1))
            page_size = int(request.GET.get('page_size', 10))
            
            offset = (page - 1) * page_size
            
            recognitions = MedicalImageRecognition.objects.filter(user_id=user_id).order_by('-created_at')
            total = recognitions.count()
            recognitions = recognitions[offset:offset + page_size]
            
            data = []
            for recognition in recognitions:
                data.append({
                    'id': recognition.id,
                    'recognition_type': recognition.recognition_type,
                    'recognition_type_display': recognition.get_recognition_type_display(),
                    'status': recognition.status,
                    'status_display': recognition.get_status_display(),
                    'suggested_department': recognition.suggested_department,
                    'created_at': recognition.created_at.isoformat(),
                    'processed_at': recognition.processed_at.isoformat() if recognition.processed_at else None
                })
            
            return JsonResponse({
                'code': 0,
                'msg': '获取成功',
                'data': {
                    'list': data,
                    'total': total,
                    'page': page,
                    'page_size': page_size
                }
            })
            
        except Exception as e:
            logger.error(f"获取识别历史失败: {e}")
            return JsonResponse({
                'code': 500,
                'msg': f'获取失败: {str(e)}',
                'data': None
            }, status=500)

class DocumentOCRView(View):
    """文档OCR识别API视图"""
    
    @method_decorator(csrf_exempt)
    @method_decorator(login_required)
    @method_decorator(rate_limit(max_requests=10, window=60))
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
    
    def post(self, request):
        """上传文档进行OCR识别"""
        try:
            if 'document' not in request.FILES:
                return JsonResponse({
                    'code': 400,
                    'msg': '请上传文档文件',
                    'data': None
                }, status=400)
            
            document_file = request.FILES['document']
            document_type = request.POST.get('document_type', 'blood_test')
            user_id = request.user_id
            
            # 验证文件类型和大小
            allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'application/pdf']
            if document_file.content_type not in allowed_types:
                return JsonResponse({
                    'code': 400,
                    'msg': '不支持的文档格式，请上传JPG、PNG或PDF格式',
                    'data': None
                }, status=400)
            
            if document_file.size > 10 * 1024 * 1024:
                return JsonResponse({
                    'code': 400,
                    'msg': '文档文件过大，请上传小于10MB的文件',
                    'data': None
                }, status=400)
            
            # 创建OCR记录
            with transaction.atomic():
                ocr_record = MedicalDocumentOCR.objects.create(
                    user_id=user_id,
                    document=document_file,
                    document_type=document_type,
                    status='processing'
                )
                
                # 调用百度OCR服务
                service = MedicalOCRService()
                result = service.extract_text_from_document(document_file)
                
                # 更新OCR结果
                if result.get('success'):
                    ocr_record.status = 'completed'
                    ocr_record.raw_response = result.get('raw_result')
                    ocr_record.extracted_text = result.get('extracted_text')
                    ocr_record.structured_data = result.get('structured_data')
                    ocr_record.medical_indicators = result.get('medical_indicators')
                    ocr_record.abnormal_values = result.get('abnormal_values')
                    ocr_record.interpretation = self._generate_interpretation(result)
                    ocr_record.recommendations = self._generate_recommendations(result)
                else:
                    ocr_record.status = 'failed'
                
                ocr_record.save()
                
                return JsonResponse({
                    'code': 0,
                    'msg': 'OCR识别完成',
                    'data': {
                        'ocr_id': ocr_record.id,
                        'status': ocr_record.status,
                        'extracted_text': ocr_record.extracted_text,
                        'structured_data': ocr_record.structured_data,
                        'medical_indicators': ocr_record.medical_indicators,
                        'abnormal_values': ocr_record.abnormal_values,
                        'interpretation': ocr_record.interpretation,
                        'recommendations': ocr_record.recommendations
                    }
                })
                
        except Exception as e:
            logger.error(f"文档OCR失败: {e}")
            return JsonResponse({
                'code': 500,
                'msg': f'OCR识别失败: {str(e)}',
                'data': None
            }, status=500)
    
    def _generate_interpretation(self, result):
        """生成解读结果"""
        if not result.get('medical_indicators'):
            return "文档识别完成，建议咨询医生进行专业解读"
        
        indicators = result['medical_indicators']
        abnormal_count = len(result.get('abnormal_values', []))
        
        if abnormal_count == 0:
            return "检测结果在正常范围内，各项指标未见明显异常"
        else:
            return f"检测结果中有{abnormal_count}项指标异常，建议咨询专科医生进行详细解读"
    
    def _generate_recommendations(self, result):
        """生成建议"""
        recommendations = []
        
        if result.get('abnormal_values'):
            recommendations.append("检测结果存在异常值，建议咨询专科医生")
            recommendations.append("建议进行进一步检查以明确诊断")
        
        recommendations.append("请保留检查报告，便于医生参考")
        return '\n'.join(recommendations)
    
    def get(self, request):
        """获取用户的OCR历史"""
        try:
            user_id = request.user_id
            page = int(request.GET.get('page', 1))
            page_size = int(request.GET.get('page_size', 10))
            
            offset = (page - 1) * page_size
            
            ocr_records = MedicalDocumentOCR.objects.filter(user_id=user_id).order_by('-created_at')
            total = ocr_records.count()
            ocr_records = ocr_records[offset:offset + page_size]
            
            data = []
            for ocr in ocr_records:
                data.append({
                    'id': ocr.id,
                    'document_type': ocr.document_type,
                    'document_type_display': ocr.get_document_type_display(),
                    'status': ocr.status,
                    'status_display': ocr.get_status_display(),
                    'created_at': ocr.created_at.isoformat(),
                    'processed_at': ocr.processed_at.isoformat() if ocr.processed_at else None
                })
            
            return JsonResponse({
                'code': 0,
                'msg': '获取成功',
                'data': {
                    'list': data,
                    'total': total,
                    'page': page,
                    'page_size': page_size
                }
            })
            
        except Exception as e:
            logger.error(f"获取OCR历史失败: {e}")
            return JsonResponse({
                'code': 500,
                'msg': f'获取失败: {str(e)}',
                'data': None
            }, status=500)

class MultiModalConsultationView(View):
    """多模态问诊API视图"""
    
    @method_decorator(csrf_exempt)
    @method_decorator(login_required)
    @method_decorator(rate_limit(max_requests=5, window=60))
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
    
    def post(self, request):
        """创建多模态问诊"""
        try:
            user_id = request.user_id
            
            # 获取表单数据
            symptom_description = request.POST.get('symptom_description', '')
            duration = request.POST.get('duration', '')
            severity = request.POST.get('severity')
            
            # 获取文件
            image_file = request.FILES.get('image')
            document_file = request.FILES.get('document')
            
            if not symptom_description and not image_file and not document_file:
                return JsonResponse({
                    'code': 400,
                    'msg': '请至少提供症状描述、图片或文档中的一项',
                    'data': None
                }, status=400)
            
            # 生成问诊ID
            consultation_id = f"MMC_{uuid.uuid4().hex[:12].upper()}"
            
            with transaction.atomic():
                # 创建问诊记录
                consultation = MultiModalConsultation.objects.create(
                    user_id=user_id,
                    consultation_id=consultation_id,
                    symptom_description=symptom_description,
                    duration=duration,
                    severity=int(severity) if severity else None,
                    status='processing'
                )
                
                # 综合分析
                analysis_service = MultiModalAnalysisService()
                analysis_result = analysis_service.analyze_consultation(
                    image_file=image_file,
                    document_file=document_file,
                    symptom_description=symptom_description
                )
                
                # 更新问诊记录
                consultation.ai_analysis = analysis_result
                consultation.suggested_department = '内科'
                consultation.urgency_level = 'medium'
                consultation.status = 'submitted'
                consultation.save()
                
                return JsonResponse({
                    'code': 0,
                    'msg': '多模态问诊创建成功',
                    'data': {
                        'consultation_id': consultation.consultation_id,
                        'status': consultation.status,
                        'suggested_department': consultation.suggested_department,
                        'urgency_level': consultation.urgency_level,
                        'analysis_result': analysis_result
                    }
                })
                
        except Exception as e:
            logger.error(f"创建多模态问诊失败: {e}")
            return JsonResponse({
                'code': 500,
                'msg': f'创建失败: {str(e)}',
                'data': None
            }, status=500)
    
    def get(self, request):
        """获取用户的多模态问诊历史"""
        try:
            user_id = request.user_id
            page = int(request.GET.get('page', 1))
            page_size = int(request.GET.get('page_size', 10))
            
            offset = (page - 1) * page_size
            
            consultations = MultiModalConsultation.objects.filter(user_id=user_id).order_by('-created_at')
            total = consultations.count()
            consultations = consultations[offset:offset + page_size]
            
            data = []
            for consultation in consultations:
                data.append({
                    'consultation_id': consultation.consultation_id,
                    'status': consultation.status,
                    'status_display': consultation.get_status_display(),
                    'symptom_description': consultation.symptom_description,
                    'suggested_department': consultation.suggested_department,
                    'urgency_level': consultation.urgency_level,
                    'created_at': consultation.created_at.isoformat(),
                    'has_image': consultation.image_recognition is not None,
                    'has_document': consultation.document_ocr is not None
                })
            
            return JsonResponse({
                'code': 0,
                'msg': '获取成功',
                'data': {
                    'list': data,
                    'total': total,
                    'page': page,
                    'page_size': page_size
                }
            })
            
        except Exception as e:
            logger.error(f"获取问诊历史失败: {e}")
            return JsonResponse({
                'code': 500,
                'msg': f'获取失败: {str(e)}',
                'data': None
            }, status=500)

@csrf_exempt
@require_http_methods(["GET", "OPTIONS"])
def get_recognition_detail(request, recognition_id):
    """获取识别详情"""
    if request.method == "OPTIONS":
        return JsonResponse({}, status=200)
    
    try:
        user_id = request.user_id
        recognition = get_object_or_404(MedicalImageRecognition, id=recognition_id, user_id=user_id)
        
        return JsonResponse({
            'code': 0,
            'msg': '获取成功',
            'data': {
                'id': recognition.id,
                'recognition_type': recognition.recognition_type,
                'recognition_type_display': recognition.get_recognition_type_display(),
                'status': recognition.status,
                'status_display': recognition.get_status_display(),
                'image_url': recognition.image.url if recognition.image else None,
                'recognized_items': recognition.recognized_items,
                'suggested_diseases': recognition.suggested_diseases,
                'suggested_department': recognition.suggested_department,
                'medical_advice': recognition.medical_advice,
                'created_at': recognition.created_at.isoformat(),
                'processed_at': recognition.processed_at.isoformat() if recognition.processed_at else None
            }
        })
        
    except Exception as e:
        logger.error(f"获取识别详情失败: {e}")
        return JsonResponse({
            'code': 500,
            'msg': f'获取失败: {str(e)}',
            'data': None
        }, status=500)

@csrf_exempt
@require_http_methods(["GET", "OPTIONS"])
def get_ocr_detail(request, ocr_id):
    """获取OCR详情"""
    if request.method == "OPTIONS":
        return JsonResponse({}, status=200)
    
    try:
        user_id = request.user_id
        ocr = get_object_or_404(MedicalDocumentOCR, id=ocr_id, user_id=user_id)
        
        return JsonResponse({
            'code': 0,
            'msg': '获取成功',
            'data': {
                'id': ocr.id,
                'document_type': ocr.document_type,
                'document_type_display': ocr.get_document_type_display(),
                'status': ocr.status,
                'status_display': ocr.get_status_display(),
                'document_url': ocr.document.url if ocr.document else None,
                'extracted_text': ocr.extracted_text,
                'structured_data': ocr.structured_data,
                'medical_indicators': ocr.medical_indicators,
                'abnormal_values': ocr.abnormal_values,
                'interpretation': ocr.interpretation,
                'recommendations': ocr.recommendations,
                'created_at': ocr.created_at.isoformat(),
                'processed_at': ocr.processed_at.isoformat() if ocr.processed_at else None
            }
        })
        
    except Exception as e:
        logger.error(f"获取OCR详情失败: {e}")
        return JsonResponse({
            'code': 500,
            'msg': f'获取失败: {str(e)}',
            'data': None
        }, status=500)